﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using CoreLibrary;
using CoreLibrary.Paging;
using Entities.DataBase;
using Entities.DataBase.Obj;
using Entities.DataBase.Persistent;
using WebService.Email;
using WebService.Service.Transfer;

namespace WebService.Service {

    public class CustomerServiceX : AbstractService, ICustomerServiceX {

        public string AddCustomer(string passport, AddCustomerRequest request) {
            return Run(passport, token => {
                   var id = Guid.NewGuid().ToString();
                   Locate<ICustomerRepository>().Add(new Customer {
                        Id           = id,
                        Name         = request.Name,
                        CName        = request.CName,
                        Sex          = request.Sex,
                        Address1     = request.Address1,
                        Email1       = request.Email1,
                        PhoneNumber1 = request.PhoneNumber1,
                        Email2       = Util.GetString(request.Email2),
                        PhoneNumber2 = Util.GetString(request.PhoneNumber2),
                        Address2     = Util.GetString(request.Address2)
                    });
                    return id;
            });
        }

        public bool UpdateCustomer(string passport, UpdateCustomerRequest request) {
            return Run(passport, token => {
                Locate<ICustomerRepository>().Update(new CustomerUpdator {
                        CustomerId   = request.CustomerId,
                        Name         = request.Name,
                        CName        = request.CName,
                        Email1       = request.Email1,
                        PhoneNumber1 = request.PhoneNumber1,
                        Address1     = request.Address1,
                        Sex          = request.Sex,
                        Email2       = Util.GetString(request.Email2),
                        PhoneNumber2 = Util.GetString(request.PhoneNumber2),
                        Address2     = Util.GetString(request.Address2)
                });
                return true;
            });
        }

        public bool RemoveCustomer(string passport, string customerId) {
            return Run(passport, token => {
                Locate<ICustomerRepository>().Remove(customerId);
                return true;
            });
        }

        public PagingResult<CustomerInfo> ListCustomers(string passport, PagingRequest request) {
            return Run(passport, token => {
                var customers = Locate<ICustomerRepository>().List(request.Keyword);
                return new PagingResult<CustomerInfo> {
                     Offset = request.Offset,
                     Total  = customers.Count,
                     Data   = customers.Skip(request.Offset).Take(request.Limit).Select(Convert).ToList()
                };
            });
        }

        public JSONSearchResult<CustomerInfo> SearchCustomers(string passport, JSONSearchRequest request) {
            return Run(passport, token => {
                var customers = Locate<ICustomerRepository>()
                                        .SearchAny(CreateExpressions(request))
                                        .OrderByDescending(c => c.DateCreated)
                                        .ToList();
                return new JSONSearchResult<CustomerInfo> {
                       Offset = request.Offset,
                       Total  = customers.Count,
                       Data   = customers.Skip(request.Offset)
                                         .Take(request.Limit)
                                         .Select(Convert)
                                         .ToList()
                };
            });
        }

        public bool SendPurchaseRequest(string passport, CreatePurchaseListRequest request) {
            return Run(passport, token => {
                EmailManager.SendEmail(new CreatePurchaseListTemplate {
                    Request = request,
                    Name = token.FirstName + " " + token.LastName
                });
                return true;
            });
        }

        private static CustomerInfo Convert(Customer customer) {
            return new CustomerInfo {
                Id             = customer.Id,
                Name           = customer.Name,
                CName          = customer.CName,
                PhoneNumber1   = customer.PhoneNumber1,
                Email1         = customer.Email1,
                Address1       = customer.Address1,
                DateCreated    = customer.DateCreated,
                Sex            = customer.Sex,
                Email2         = customer.Email2,
                PhoneNumber2   = customer.PhoneNumber2,
                Address2       = customer.Address2,
            };
        }

        protected static List<Expression<Func<Customer,bool>>> CreateExpressions(JSONSearchRequest request) {
            var criterias = request.Criterias;
            if (CollectionUtil.IsEmpty(criterias)) {
                return new List<Expression<Func<Customer, bool>>> {
                       PredicateUtil.True<Customer>()
                };
            }

            var exps = new List<Expression<Func<Customer,bool>>>();
            foreach (var criteria in criterias) {
                if ("Name".Equals(criteria.Field) && !string.IsNullOrEmpty(criteria.Data)) {
                    var criteria1 = criteria;
                    Expression<Func<Customer, bool>> func1 = p => p.Name.Contains(criteria1.Data);
                    Expression<Func<Customer, bool>> func2 = p => p.CName.Contains(criteria1.Data);
                    exps.Add(func1);
                    exps.Add(func2);
                }
                if ("PhoneNumber".Equals(criteria.Field) && !string.IsNullOrEmpty(criteria.Data)) {
                    var criteria1 = criteria;
                    Expression<Func<Customer, bool>> func1 = p => p.PhoneNumber1.Contains(criteria1.Data);
                    Expression<Func<Customer, bool>> func2 = p => p.PhoneNumber2.Contains(criteria1.Data);
                    Expression<Func<Customer, bool>> func3 = p => p.PhoneNumber3.Contains(criteria1.Data);
                    exps.Add(func1);
                    exps.Add(func2);
                    exps.Add(func3);
                }
                if ("Email".Equals(criteria.Field) && !string.IsNullOrEmpty(criteria.Data)) {
                    var criteria1 = criteria;
                    Expression<Func<Customer, bool>> func1 = p => p.Email1.Contains(criteria1.Data);
                    Expression<Func<Customer, bool>> func2 = p => p.Email2.Contains(criteria1.Data);
                    Expression<Func<Customer, bool>> func3 = p => p.Email3.Contains(criteria1.Data);
                    exps.Add(func1);
                    exps.Add(func2);
                    exps.Add(func3);
                }
                if ("Address".Equals(criteria.Field) && !string.IsNullOrEmpty(criteria.Data)) {
                    var criteria1 = criteria;
                    Expression<Func<Customer, bool>> func1 = p => p.Address1.Contains(criteria1.Data);
                    Expression<Func<Customer, bool>> func2 = p => p.Address2.Contains(criteria1.Data);
                    Expression<Func<Customer, bool>> func3 = p => p.Address3.Contains(criteria1.Data);
                    exps.Add(func1);
                    exps.Add(func2);
                    exps.Add(func3);
                }
            }
            return exps;
        }
    }
}
